/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package SeismoScope;

import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.io.Connector;
import javax.microedition.sensor.*;
import java.io.IOException;
import sUtils.*;
//import javax.microedition.io.file.*;
//import javax.microedition.io.*;




public class SeismoScope extends MIDlet {
    SeismoCanvas canvas;
    SeismoData data;

    public void startApp() {
        canvas = new SeismoCanvas(this);
        data = new SeismoData(this);
        Display.getDisplay(this).setCurrent( canvas );
        data.init();
    }

    public void pauseApp() {}

    public void destroyApp(boolean unconditional) {}

    public void close()
    {
        Display.getDisplay(this).setCurrent(null);
        data.done();
        //data.wait(200);
        canvas = null;
        data=null;
        destroyApp(true);
        notifyDestroyed();
    }

    public void onData( double x, double y, double z )
    {
       canvas.setData(x,y,z);
    }

    public void onMenu( String id )
    {
        if (id.equalsIgnoreCase("quit"))
        {
            close();
        }
        if (id.equalsIgnoreCase("rec"))
        {
            if (data.recording()) data.closeCSV(); else data.createCSV();
            canvas.setRecState(data.recording()?1:0);
        }

    }


   class SeismoCanvas extends Canvas {
       SeismoScope parent;
       Menu menu = new Menu();
       Timer timer;
       double dx[],dy[],dz[],ds[];
       long lastTouch=0;
       int count;
       boolean cleared = false;
       
       public SeismoCanvas( SeismoScope p ) {
            parent = p;
            dx = new double[400];
            dy = new double[400];
            dz = new double[400];
            ds = new double[400];
            clear();
            setFullScreenMode(true);
            menu.init(getWidth(), getHeight(), 0, true);
            menu.add(Lang.word("Quit", "Beenden"), "quit");
            menu.add(null,null);
            menu.add(Lang.word("Record", "Aufnahme"), "rec");
            menu.setState("rec", 0);
            lastTouch = System.currentTimeMillis();
            timer = new Timer();
            timer.schedule(new updateTask(this), 0, 200);
        }

       public void setData( double x, double y, double z )
       {
           dx[0]+=x; dy[0]+=y; dz[0]+=z;
       }

       public void setRecState( int i )
       {
           menu.setState("rec", i);
       }

       void clear()
       {
           for ( int i=0; i<400; i++ ) { dx[i]=dy[i]=dz[i]=ds[i]=0; }
           count=0;
       }

       class updateTask extends TimerTask {
            private SeismoCanvas canvas;
            updateTask( SeismoCanvas c ){  canvas = c;  }
            public void run() {
                dx[0] = dx[0]*0.6+dx[1]*0.4;
                dy[0] = dy[0]*0.6+dy[1]*0.4;
                dz[0] = dz[0]*0.6+dz[1]*0.4;
                ds[0] = ds[0]*0.6+ds[1]*0.4;
                for ( int i=399; i>0; i-- )
                { 
                    dx[i]=dx[i-1];
                    dy[i]=dy[i-1];
                    dz[i]=dz[i-1];
                    ds[i]=ds[i-1];
                }
                dx[0]=dy[0]=dz[0]=ds[0]=0; count++;
                canvas.repaint();
            }
        }

        public void paint(Graphics g) {
            if ( (System.currentTimeMillis() - lastTouch < 60000 ) )
            {
                int width = getWidth();
                int height = getHeight();
                int nx,ny,nz,ns;
                g.setColor(0x2000);
                g.fillRect(0,0,width,height);
                for ( int y=0; y<400; y++ )
                {
                    nx = (int)dx[y];
                    ny = (int)dy[y];
                    nz = (int)dz[y];
                    ns = (int)ds[y];

                    if (((count+400-y)%20)==0)
                    {
                        g.setColor(0x4000);
                        g.fillRect(0,y,width,1);
                    }
                    g.setColor(0x00ff00);
                    g.fillRect(40-nx, y, 1+nx*2, 1);
                    g.fillRect(90-ny, y, 1+ny*2, 1);
                    g.fillRect(140-nz, y, 1+nz*2, 1);
                    g.setColor(0xffff00);
                    g.fillRect(210-ns, y, 1+ns*2, 1);
                }
               //g.setColor(0xff00);
               // g.setFont( Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL));
                menu.paint(g);
                cleared=false;
            }
            else
            if (!cleared)
            {
                g.setColor(0xf);
                g.fillRect(0,0,getWidth(),getHeight());
                cleared=true;
            }
        }

        
        
        public void keyPressed( int k )
        {
            if (k==-10)
            {
                lastTouch = System.currentTimeMillis();
                menu.show();
            }
        }

        public void pointerPressed( int x, int y )
        {
            if (menu.active) parent.onMenu( menu.hit(x, y)); else
            {
                lastTouch = System.currentTimeMillis();
                
            }
        }

        public void pointerDrag( int x, int y )
        {
            if (menu.active) menu.hit(x, y); 
        }

        public void pointerReleased( int x, int y )
        {
            if (menu.active) menu.release();
        }

        

   }


   class SeismoData extends Thread implements DataListener
   {
        SeismoScope parent = null;
        SensorConnection sensor=null;
        File csv = new File();
        boolean first=true, running=false;
        double dx,dy,dz,ds,ox,oy,oz;
        long lastSave=0;

        public SeismoData( SeismoScope p )
        {
            parent = p;
            start();
        }

        boolean createCSV()
        {
            synchronized(this)
            {
                if (!csv.create( "/mmc/seismo_"+Strings.getDateID()+".csv" ))
                csv.create( "/record/seismo_"+Strings.getDateID()+".csv" );
                lastSave = System.currentTimeMillis();
            }
            return csv.opened();
        }

        void closeCSV()
        {
            synchronized(this)
            {
                csv.close();
            }
        }

        boolean recording()
        {
            synchronized(this) { return csv.opened(); }
        }

        boolean init()
        {
            SensorInfo[] sensors = SensorManager.findSensors(null,null);
            for ( int i=0; i<sensors.length; i++ )
            {
                if (sensors[i].getQuantity().equalsIgnoreCase("acceleration"))
                {
                    try {
                        sensor = (SensorConnection) Connector.open(sensors[i].getUrl());
                        sensor.setDataListener(this, 1);
                    } catch (IOException e) { }
                    break;
                }
            }
            return true;
        }

        void done()
        {
            running=false;
            csv.close();
            if (sensor!=null) try { sensor.close();  } catch (IOException e) { }
        }

        public void run()
        {
            init();
            this.setPriority(Thread.MAX_PRIORITY);
            running=true;
            
            while (running)
            {
                try { Thread.sleep(30000); } catch (Exception e) {}
                synchronized(this)
                {
                    csv.writeStr( Strings.getDateTimeStr() + ";"+(int)(ds)+";\r\n");
                    ds=0;
                    lastSave = System.currentTimeMillis();
                }
            }
        }

        public void dataReceived( SensorConnection conn, Data[] arg, boolean lost )
        {
            double x = arg[0].getDoubleValues()[0];
            double y = arg[1].getDoubleValues()[0];
            double z = arg[2].getDoubleValues()[0];
            synchronized(this)
            {
                if (!first)
                {
                    dx=Math.abs(x-ox)*5;
                    dy=Math.abs(y-oy)*5;
                    dz=Math.abs(z-oz)*5;
                    ds += (dx+dy+dz)/100;
                    parent.onData(dx,dy,dz);
                }
                else
                {
                    first=false; ds=0;
                }
                ox=x; oy=y; oz=z;
            }
        }
   }
}